package com.sh.data.engine.domain.authority.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sh.data.engine.common.exception.BusinessException;
import com.sh.data.engine.common.util.ServletUtils;
import com.sh.data.engine.domain.authority.model.domain.RoleDomain;
import com.sh.data.engine.domain.authority.model.domain.UserProjectDomain;
import com.sh.data.engine.domain.authority.model.mapper.RoleDomainMapper;
import com.sh.data.engine.domain.authority.model.mapper.RoleEntityMapper;
import com.sh.data.engine.domain.authority.model.mapper.SimpleMenuEntityMapper;
import com.sh.data.engine.domain.authority.model.param.RoleParam;
import com.sh.data.engine.domain.authority.service.RoleMenuService;
import com.sh.data.engine.domain.authority.service.RoleService;
import com.sh.data.engine.domain.authority.service.UserProjectService;
import com.sh.data.engine.domain.base.model.PageResult;
import com.sh.data.engine.domain.base.model.UserContext;
import com.sh.data.engine.domain.util.ConvertUtil;
import com.sh.data.engine.domain.workspace.manager.service.UserService;
import com.sh.data.engine.repository.dao.authority.RoleMapper;
import com.sh.data.engine.repository.dao.authority.entity.RoleEntity;
import com.sh.data.engine.repository.dao.authority.entity.RoleMenuEntity;
import com.sh.data.engine.repository.dao.authority.entity.UserProjectEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author: mengzheng.mhc
 * @date: 2024/6/25 11:02
 */
@Service
@Slf4j
public class RoleServiceImpl extends ServiceImpl<RoleMapper, RoleEntity> implements RoleService {

    @Autowired
    private RoleMenuService roleMenuService;

    @Autowired
    private UserProjectService userProjectService;

    @Lazy
    @Autowired
    private UserService userService;

    @Value("${hufu.xuelangOS.editRoleURl:null}")
    private String editRoleUrl;

    @Value("${hufu.xuelangOS.deleteRoleURl:null}")
    private String deleteRoleUrl;

    private CloseableHttpClient client;
    @Autowired
    private RoleEntityMapper roleEntityMapper;
    @Autowired
    private RoleDomainMapper roleDomainMapper;
    @Autowired
    private SimpleMenuEntityMapper simpleMenuEntityMapper;

    @PostConstruct
    private void init() {
        if (client == null) {
            client = HttpClients.createMinimal();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "engineTransactionManager")
    public Boolean addRole(RoleParam roleParam, Boolean execSecurityFlag) {
        doAdd(roleParam, execSecurityFlag);
        return true;
    }

    @Override
    public Long addRoleReturnId(RoleParam roleParam) {
        RoleEntity entity = doAdd(roleParam, true);
        return entity.getId();
    }

    @Override
    public Integer getRoleIdByUserId(String userId) {
        return userProjectService.list(
                        new LambdaQueryWrapper<UserProjectEntity>()
                                .eq(UserProjectEntity::getUserId, userId)
                                .eq(UserProjectEntity::getProjectId, ServletUtils.getProjectId()))
                .stream()
                .map(UserProjectEntity::getRoleId)
                .findFirst()
                .orElse(null);
    }

    @Override
    public String getRoleNameByRoleId(Integer roleId) {
        if (roleId != null) {
            RoleEntity roleEntity = this.getById(roleId);
            if (roleEntity != null) {
                return roleEntity.getRoleName();
            }
        }
        return "";
    }

    /**
     * 添加角色信息。
     * 通过RoleParam参数创建一个新的角色实体，并进行相应的业务逻辑处理，包括：
     * 1. 根据RoleParam映射创建RoleEntity。
     * 2. 设置角色为非系统角色。
     * 3. 检查角色名称是否重复，如果重复则抛出业务异常。
     * 4. 保存角色实体。
     * 5. 根据角色的菜单列表创建并保存RoleMenuEntity实体，建立角色与菜单的关联关系。
     *
     * @param roleParam        添加角色的参数，包含角色的基本信息和菜单权限信息。
     * @param execSecurityFlag 指示是否执行安全相关的逻辑，此处未使用但保留以备将来可能的需求。
     * @return 新增的角色实体。
     * @throws BusinessException 如果角色名称已存在，则抛出此异常。
     */
    private @NotNull RoleEntity doAdd(RoleParam roleParam, Boolean execSecurityFlag) {
        // 如果 execSecurityFlag 为 true，进行额外的权限验证
//        if (execSecurityFlag && !hasPermissionToDeleteRole(roleParam.getId())) {
//            throw new BusinessException("无权限删除该角色");
//        }
        // 根据参数映射创建角色实体
        RoleEntity roleEntity = roleEntityMapper.map(roleParam);
        // 设置角色为非系统角色
        // 设置为普通角色
        roleEntity.setIsSystem(0);

        // 确保新实体的 ID 为空，以便数据库自动生成
        roleEntity.setId(null);

        // 自定义角色需要从前端获取空间id存入role表
        Long projectId = roleParam.getProjectId() == null ? ServletUtils.getProjectId() : roleParam.getProjectId();
        roleEntity.setProjectId(projectId);

        // 从userservice获取创建人ID
        String userId = UserContext.getUserId();
        roleEntity.setCreatorId(userId);


        // 查询是否有同名的角色存在
        final long count =
                this.count(
                        new LambdaQueryWrapper<RoleEntity>()
                                .eq(RoleEntity::getRoleName, roleParam.getRoleName()));
        // 如果存在同名角色，则抛出业务异常
        if (count > 0) {
            throw new BusinessException("无法创建重名角色：" + roleParam.getRoleName());
        }
        // 保存角色实体
        this.save(roleEntity);

        // 初始化角色菜单实体列表
        List<RoleMenuEntity> roleMenuEntities = new ArrayList<>();
        // 遍历角色的菜单列表，创建并填充角色菜单实体，然后添加到列表中
        for (RoleDomain.SimpleMenuEntity simpleMenuEntity : roleParam.getMenuList()) {
            RoleMenuEntity roleMenuEntityEntity = new RoleMenuEntity();
            roleMenuEntityEntity.setRoleId(roleEntity.getId());
            roleMenuEntityEntity.setMenuId(simpleMenuEntity.getMenuId());
            roleMenuEntityEntity.setReadWriteStatus(simpleMenuEntity.getReadWriteStatus());
            roleMenuEntities.add(roleMenuEntityEntity);
        }
        // 批量保存角色菜单实体列表
        roleMenuService.saveBatch(roleMenuEntities);
        // 返回新增的角色实体
        return roleEntity;
    }

    @Override
    public Boolean editRole(RoleParam roleParam, Boolean execSecurityFlag) {
        RoleEntity roleEntityById = this.getById(roleParam.getId());
        // 如果 execSecurityFlag 为 true，进行额外的权限验证
//        if (execSecurityFlag && !hasPermissionToDeleteRole(roleParam.getId())) {
//            throw new BusinessException("无权限删除该角色");
//        }

        if (roleEntityById == null) {
            throw new BusinessException("id为" + roleParam.getId() + "的角色不存在");
        } else if (roleEntityById.getIsSystem() != null && roleEntityById.getIsSystem() == 1) {
            throw new BusinessException("无法修改系统角色");
        }

        final long count =
                this.count(
                        new LambdaQueryWrapper<RoleEntity>()
                                .eq(RoleEntity::getRoleName, roleParam.getRoleName())
                                .ne(RoleEntity::getId, roleParam.getId()));

        if (count > 0) {
            throw new BusinessException("角色名：" + roleParam.getRoleName() + "已存在");
        }

        RoleEntity roleEntity = roleEntityMapper.map(roleParam);
        this.updateById(roleEntity);

        // 先删除关系表 然后新增关系表
        roleMenuService.remove(
                new LambdaQueryWrapper<RoleMenuEntity>()
                        .eq(RoleMenuEntity::getRoleId, roleEntityById.getId()));

        if (CollectionUtils.isNotEmpty(roleParam.getMenuList())) {
            List<RoleMenuEntity> roleMenuEntities =
                    roleParam.getMenuList().stream()
                            .map(
                                    m -> {
                                        RoleMenuEntity entity = new RoleMenuEntity();
                                        entity.setRoleId(roleParam.getId());
                                        entity.setMenuId(m.getMenuId());
                                        entity.setReadWriteStatus(m.getReadWriteStatus());
                                        return entity;
                                    })
                            .collect(Collectors.toList());
            roleMenuService.saveBatch(roleMenuEntities);
        }
        // 首先查询出受"修改角色菜单"影响的用户列表
        //  List<UserDomain> userDomainList = userService.findByRoleId(roleParam.getId());
        //  if (CollectionUtils.isNotEmpty(userDomainList)) {
        //    apiService.doUserListApi(userDomainList);
        //    }
        return true;
    }

    @Override
    public Boolean delRole(int id, Boolean execSecutityFlag) {
        RoleEntity roleEntity = this.getById(id);
        if (roleEntity == null) {
            throw new BusinessException("id为" + id + "的角色不存在");
        }
        if (Objects.equals(roleEntity.getIsSystem(), 1)) {
            throw new BusinessException("无法修改系统角色");
        }

        // 如果 execSecutityFlag 为 true，进行额外的权限验证
//        if (execSecutityFlag && !hasPermissionToDeleteRole(id)) {
//            throw new BusinessException("无权限删除该角色");
//        }

        // 如果该角色被某个用户绑定 则无法删除
//        List<UserDomain> userDomainList = userService.findByRoleId(id);
        List<UserProjectDomain> userProjectListByRoleId = userProjectService.getUserProjectListByRoleId(id);


        if (CollectionUtils.isNotEmpty(userProjectListByRoleId)) {
            throw new BusinessException(
                    "该角色："
                            + roleEntity.getRoleName()
                            + " 被用户使用，无法删除");

        }

        this.removeById(id);

        roleMenuService.remove(
                new LambdaQueryWrapper<RoleMenuEntity>().eq(RoleMenuEntity::getRoleId, id));

        return true;
    }

    @Override
    public PageResult<RoleDomain> list(Integer pageNum, Integer pageSize,
                                       String roleName, String roleDesc) {
        final LambdaQueryWrapper<RoleEntity> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(roleName)) {
            queryWrapper.like(RoleEntity::getRoleName, roleName);
        }
        if (StringUtils.isNotBlank(roleDesc)) {
            queryWrapper.like(RoleEntity::getRoleDesc, roleDesc);
        }

        // 查询当前工作空间的角色或者系统角色
        queryWrapper.and(wrapper ->
                wrapper.eq(RoleEntity::getProjectId, ServletUtils.getProjectId())
                        .or()
                        .eq(RoleEntity::getIsSystem, 1));
        queryWrapper.orderByAsc(List.of(RoleEntity::getIsSystem, RoleEntity::getRoleName));

        if (pageNum != null && pageSize != null) {
            // 如果开启分页
            final Page<RoleEntity> page = this.page(new Page<>(pageNum, pageSize), queryWrapper);

            PageResult<RoleEntity> roleEntityPageResult =
                    new PageResult<>(page.getTotal(), page.getRecords(), pageNum, pageSize);

            PageResult<RoleDomain> roleDomainPageResult =
                    ConvertUtil.convertPageInfo(roleEntityPageResult, RoleDomain.class);

            List<RoleDomain> roleDomainList = roleDomainPageResult.getResult();

            for (RoleDomain roleDomain : roleDomainList) {
                // 获取更新人姓名
                String updaterId = roleDomain.getUpdaterId();
                if (updaterId != null) {
                    String userName = userService.getUserNameById(updaterId);
                    if (userName != null) {
                        roleDomain.setUpdaterName(userName);
                    }
                }
            }
            return roleDomainPageResult;
        }

        List<RoleEntity> roleEntityList = this.list(queryWrapper);

        List<RoleDomain> roleDomainList = roleDomainMapper.map(roleEntityList);

        PageResult<RoleDomain> roleDomainPageResult = new PageResult<>(roleDomainList);

        return roleDomainPageResult;
    }

    @Override
    public PageResult<RoleDomain> listSysRole(Integer pageNum, Integer pageSize,
                                              String roleName, String roleDesc) {
        final LambdaQueryWrapper<RoleEntity> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(roleName)) {
            queryWrapper.like(RoleEntity::getRoleName, roleName);
        }
        if (StringUtils.isNotBlank(roleDesc)) {
            queryWrapper.like(RoleEntity::getRoleDesc, roleDesc);
        }

        queryWrapper.orderByDesc(RoleEntity::getUpdateTime);
        queryWrapper.eq(RoleEntity::getIsSystem, 1);

        if (pageNum != null && pageSize != null) {
            // 如果开启分页
            final Page<RoleEntity> page = this.page(new Page<>(pageNum, pageSize), queryWrapper);

            PageResult<RoleEntity> roleEntityPageResult =
                    new PageResult<>(page.getTotal(), page.getRecords(), pageNum, pageSize);

            PageResult<RoleDomain> roleDomainPageResult =
                    ConvertUtil.convertPageInfo(roleEntityPageResult, RoleDomain.class);

//            List<RoleDomain> roleDomainList = roleDomainPageResult.getResult();
//
//            for (RoleDomain roleDomain : roleDomainList) {
//                // 获取更新人姓名
//                String updaterId = roleDomain.getUpdaterId();
//                if (updaterId != null) {
//                    UserDomain userDomain = userService.getUserById(updaterId);
//                    if (userDomain != null) {
//                        roleDomain.setUpdaterName(userDomain.getUserName());
//                    }
//                }
//            }
            return roleDomainPageResult;
        }

        List<RoleEntity> roleEntityList = this.list(queryWrapper);

        List<RoleDomain> roleDomainList = roleDomainMapper.map(roleEntityList);

        PageResult<RoleDomain> roleDomainPageResult = new PageResult<>(roleDomainList);

        return roleDomainPageResult;
    }

    /**
     * @description : 查询包含某菜单的角色
     * @author : tinglan.ys
     * @date : 2022/1/26
     */
    @Override
    public List<RoleDomain> findByMenuId(Long menuId) {
        final List<RoleMenuEntity> menuEntityList =
                roleMenuService.list(
                        new LambdaQueryWrapper<RoleMenuEntity>().eq(RoleMenuEntity::getMenuId, menuId));
        final List<Long> roleIds =
                menuEntityList.stream().map(e -> e.getRoleId()).collect(Collectors.toList());
        final List<RoleEntity> roleEntityList = this.listByIds(roleIds);
        List<RoleDomain> roleDomainList = roleDomainMapper.map(roleEntityList);
        return roleDomainList;
    }

    @Override
    public RoleDomain getByIdWithMenu(Long id) {

        RoleEntity roleEntity = this.getById(id);
        RoleDomain roleDomain = roleDomainMapper.map(roleEntity);

        // 找到该角色的拥有的菜单
        List<RoleMenuEntity> list =
                roleMenuService.list(
                        new LambdaQueryWrapper<RoleMenuEntity>().eq(RoleMenuEntity::getRoleId, id));

        List<RoleDomain.SimpleMenuEntity> simpleMenuEntities = simpleMenuEntityMapper.map(list);

        roleDomain.setMenuList(simpleMenuEntities);

        // 获取更新人姓名
        String updaterId = roleDomain.getUpdaterId();
        if (updaterId != null) {
            roleDomain.setUpdaterName(userService.getUserDetailByIdWithoutRole(updaterId).getDisplayName());
        }

        return roleDomain;
    }

//    private boolean hasPermissionToDeleteRole(Long roleId) {
//        // 检查当前角色是否模块权限里勾选了空间角色-编辑，是则有权限编辑新增删除角色
//        RoleEntity roleEntity = this.getById(roleId);
//
//        if (roleEntity.getIsSystem() == null || roleEntity.getIsSystem() != 1) {
//            // 找到该角色的拥有的菜单
//            List<RoleMenuEntity> list =
//                    roleMenuService.list(
//                            new LambdaQueryWrapper<RoleMenuEntity>().eq(RoleMenuEntity::getRoleId, roleId));
//
//            List<RoleDomain.SimpleMenuEntity> simpleMenuEntities = simpleMenuEntityMapper.map(list);
//            if (simpleMenuEntities.stream().anyMatch(e -> e.getMenuId() == 50L && e.getReadWriteStatus() == 1)) {
//                return true;
//            }
//            throw new BusinessException(
//                    "该角色：" + roleEntity.getRoleName()
//                            + " 没有空间角色模块编辑权限");
//
//        }
//        throw new BusinessException("无法编辑或删除系统角色");
//    }

}



